#include "obuinfo.h"
#include "lanefunction.h"
#include "vehplateutils.h"
#include <QtEndian>
#include <QTextStream>
#include <QDebug>


ObuInfo::ObuInfo(QObject *parent) :
    QObject(parent)
{
    memset(&m_rawSysInfoFile, 0, sizeof m_rawSysInfoFile);
    memset(&m_rawCfg, 0, sizeof m_rawCfg);
}

bool ObuInfo::setObuInfo(const quint8 *sysInfo, quint8 sizeOfSysInfo, const quint8 *obuCfg)
{
    if((sizeOfSysInfo < MIN_SYSFILE_SIZE) ||
            (sizeOfSysInfo > sizeof(m_rawSysInfoFile)))
    {
        qDebug() << "sizeOfSysInfo 字节数不合法";
        return false;
    }
    RawObuSysInfoFile rawSys;
    memset(&rawSys,0,sizeof rawSys);
    memcpy(&rawSys, sysInfo, sizeOfSysInfo);
    QDate d1,d2;
    if(!bcd2date(&d1,rawSys.contractSignedDate))
    {
        qDebug() << "OBU注册时间非法";
        return false;
    }
    if (!bcd2date(&d2, rawSys.contractExpiredDate))
    {
        qDebug() << "OBU过期时间非法";
        return false;
    }

    this->m_contractSignedDate = d1;
    this->m_contractExpiredDate = d2;
    memcpy(&this->m_rawSysInfoFile, &rawSys, sizeof rawSys);
    memcpy(&this->m_rawCfg, obuCfg, OBU_CFG_SIZE);
    // 对山东发行的OBU，解析其系统文件内的车牌和车牌颜色
    // "\xc9\xbd\xb6\xab": "山东"的GB2312编码
    if (0==memcmp("\xc9\xbd\xb6\xab", rawSys.contractProvider, 4))
    {
        setVehPlateNumber(rawSys.vehicleLicencePlateNumber, sizeof(rawSys.vehicleLicencePlateNumber));
        setVehPlateColor(rawSys.vehicleLicencePlateColor[0], rawSys.vehicleLicencePlateColor[1]);
    }
    return true;
}

void ObuInfo::setVehPlateNumber(quint8 *pPlate, int nLen)
{
    // 车牌转换为UTF-8
    QByteArray ba((char *)pPlate, nLen);
    // 正常车牌以\x00结束
    ba.replace('\x00', ' ');
    // 有的测试OBU没有在系统信息文件中写车牌，该部分填充全\xFF，已经查询过GB2312编码没有\xFF
    ba.replace('\xFF', ' ');
    m_vehicleLicencePlateNumber=QTextCodec::codecForName("GB2312")->toUnicode(ba).trimmed();
}

void ObuInfo::setVehPlateColor(quint8 bHi, quint8 bLo)
{
    // 车牌颜色，确实存在车牌相同、车牌颜色不同的车辆，所以必须要存储车牌颜色
    if ((0xFF==bHi) ||
        (0xFF==bLo))
    {
        // 有的OBU没有写车牌颜色
        m_vehicleLicencePlateColor=0;
    }
    else
    {
        m_vehicleLicencePlateColor=bLo;
    }
}

bool ObuInfo::setObuInfo(const QString &sysInfo, const QString &obuCfg)
{
    if(sysInfo.length() > MAX_SYSFILE_SIZE*2)
        return false;
    if(obuCfg.length()!=OBU_CFG_SIZE*2)
        return false;
    quint8 rawSys[MAX_SYSFILE_SIZE];
    quint8 rawCfg[OBU_CFG_SIZE];
    if (!hex2Raw(rawSys, sysInfo.toStdString().c_str(), sysInfo.length()))
    {
        return false;
    }
    if (!hex2Raw(rawCfg, obuCfg.toStdString().c_str(), obuCfg.length()))
    {
        return false;
    }
    return setObuInfo(rawSys, sysInfo.length()/2, rawCfg);
}

bool ObuInfo::setCipheredVehInfoFile(const quint8 *vehInfoFile, quint8 fileLen)
{
    memcpy(this->m_cipheredVehInfo, vehInfoFile, fileLen);
    return true;
}

quint32 ObuInfo::getMacId() const
{
    return qFromBigEndian(this->m_rawCfg.macID);
}

bool ObuInfo::getTampered() const
{
    return testBit(this->m_rawCfg.obuStatus, 1);
}

bool ObuInfo::getLocked() const
{
    return !testBit(this->m_rawCfg.obuStatus, 2);
}

bool ObuInfo::hasCpuCard() const
{
    bool iccPresent=!testBit(this->m_rawCfg.obuStatus, 7);
    bool iccIsCpuCard=!testBit(this->m_rawCfg.obuStatus, 4);
    bool iccStatus=!testBit(this->m_rawCfg.obuStatus, 3);
    return iccPresent && iccIsCpuCard && iccStatus;
}

bool ObuInfo::isFromShandong() const
{
    return 0==memcmp("\xc9\xbd\xb6\xab", this->m_rawSysInfoFile.contractProvider, 4);
}

QString ObuInfo::getContractSN() const
{
    char szSN[20];
    raw2HexStr(szSN, this->m_rawSysInfoFile.contractSerialNumber, sizeof this->m_rawSysInfoFile.contractSerialNumber);
    return szSN;
}

QDate ObuInfo::getSignedDate() const
{
    return this->m_contractSignedDate;
}

QDate ObuInfo::getExpiredDate() const
{
    return this->m_contractExpiredDate;
}

QString ObuInfo::getVehicleLicencePlateNumber() const
{
    return this->m_vehicleLicencePlateNumber;
}

QString ObuInfo::getVehicleLicencePlateColorAndNumber() const
{
    return VehPlateUtils::getVehicleLicencePlateColorAndNumber(
        getVehicleLicencePlateColor(),
        getVehicleLicencePlateNumber());
}

quint16 ObuInfo::getVehicleLicencePlateColor() const
{
    return this->m_vehicleLicencePlateColor;
}
